总结
traefik
可以感知服务器内的服务并监控其的健康状态。还可以为服务分配路由,即管理路由。trakfik
服务启动可以设置在默认的 80 端口,访问域名映射到服务器 ip 后,会经过traefik
服务,traefik
通过路由匹配规则(例如请求头的Host
) 做为判断依据,反向代理到不同服务上。traefik
更多的配置可以通过CLI
传参 或者 读取/etc/traefik/traefik.toml
配置文件。在docker
中使用traefik
,则可以将traefik.toml
上传到容器内或直接使用 volumes 挂载- ./traefik.toml:/etc/traefik/traefik.toml
traefik.toml
accessLog
:访问日志,记录了访问信息log
:日志文件,记录了错误信息api
:api 配置,包含了仪表板显隐,非安全模式开启http.routers
: 路由配置,指定路由匹配规则(例如Path、Host等),和对应服务
- 可以通过
traefik.toml
指定路由匹配规则和服务。但如果在docker
中使用,traekfix
提供了更便捷的写法,只要在服务的labels
指定元信息,例如yamllabels: - "traefik.http.routers.whoami.rule=Host(`whoami.docker.local`)"`
traefik
便能自动读取labels
的路由匹配规则和本服务关联。即traefik
自动读取容器的标签生成路由规则。
疑问
- [ ] acme.json 为什么要赋 600 权限,防止容器内更改吗?
- [ ] api.insecure 非安全模式,该模式官方不推荐开启,但默认是开启状态。开启和不开启有什么区别
提问
- [x] 在服务器成功搭建 traefik
如果只有服务器但没有域名,可以通过修改本地的hosts
文件,以达到域名解析效果。我的服务器 80 端口被占用,但可以将traefik
启动在 81 端口,效果也一样。
因为本质是访问域名映射到服务器 ip 后,会经过traefik
服务,traefik
通过路由匹配规则(例如请求头的Host
) 做为判断依据,反向代理到不同服务上。 - [x] 我们如何配置并查看 traefik 的 AccessLog
AccessLog:访问日志,配置traefik.toml
文件的accessLog
字段,后续查看log/traefik-access.json
即可看到访问日志,也可以将log
文件夹挂载到容器内,这样可以在宿主机直接查看日志。toml[accessLog] # Sets the file path for the access log. If not specified, stdout will be used. # Intermediate directories are created if necessary. # # Optional # Default: os.Stdout # filePath = "log/traefik-access.json" # Format is either "json" or "common". # # Optional # Default: "common" # format = "json" [accessLog.fields] defaultMode = "keep" [accessLog.fields.headers] defaultMode = "keep"
- [x] 我们如何定位 traefik 启动失败的问题
配置traefik.toml
文件的log
字段,后续查看log/traefik.log
即可看到日志,记录了启动失败的原因。toml[log] filePath = "log/traefik.log" format = "json"
1. 前提提要、场景
至此,已经可以使用 Docker 进行前端应用的部署,并且提供对外服务。但好像,除了使用容器启动服务外,和传统方式并无二致,以前管理进程,现在管理容器。
依然有以下两个痛点:
- 我使用 docker 新跑了一个服务,如何让它被其它服务所感知或直接被互联网所访问呢?
- 我使用 docker 跑了 N 个服务,我怎么了解所有的服务的健康状态及路由呢?
需要一个基于服务发现的网关建设: Traefik。
2. traefik 搭建
traefik 是一个现代化的反向代理与负载均衡器。它可以很容易地同 Docker 集成在一起使用。每当 Docker 容器部署成功,便可以自动在网络上进行访问。
乍一看跟 nignx 有点相似,但两者维度不同,有较大差别,
- nginx 维度是资源,注重静态资源。
- traefik 维度是服务,注重的是服务,例如 nginx 提供的静态服务器。结合 docker 来看,docker 容器中提供不同服务都可以被 traefik 感知和监控。
traefik 可以做到以下
- TLS。部署域名将可直接使用 HTTPS 进行访问
- 自动收集报错日志
- AccessLog。会自动收集每个服务的请求日志
- 自动收集每个服务的健康状态
2.1 使用 docker compose 启动 traefik 服务
version: '3'
services:
traefik:
image: traefik:v2.5
command: --api.insecure=true --providers.docker # 启用 web UI 并告诉 Traefik 监听 docker
ports:
- "80:80" # http 服务端口
- "8080:8080" # Web UI (由 --api.dashboard=true 开启,默认开启)
volumes:
- /var/run/docker.sock:/var/run/docker.sock # 使得 traefik 可以监听 docker 事件
docker compose up
启动服务后,会显示 traefik_network
的网络名称,如果未显示,可以使用 docker network ls
查看。
2.2 启动一个任意服务,让 traefik 监控
例如 whoami 的简易版 Web 服务,它将会在页面上打印出一些头部信息。
version: '3'
services:
# 该镜像提供的服务,会返回显示自身的 `header` 信息
whoami:
image: containous/whoami
labels:
# 设置Host 为 whoami.docker.localhost 进行域名访问
# 后续请求,只要请求头为 whoami.docker.localhost,便会被 traefik 代理到该服务上。
# traefik.http.routers.x, x 只是一个路由名称,一般是与最后一级域名一致。
# 标签是一种将元数据应用于 Docker 对象的机制,Traefik 自动读取容器的标签生成动态配置来更新路由规则。
- "traefik.http.routers.whoami.rule=Host(`whoami.docker.local`)"
# 使用已存在的 traefik 的 network
networks:
external:
name: traefik_default # 使用上方 traefik 服务的网络名称
whoami:
- 暴露了一个 http 服务,会返回显示自身的
header
信息 - 配置了容器的 labels,是一种将元数据应用于 Docker 对象的机制,Traefik 自动读取容器的标签生成动态配置来更新路由规则。
此时通过 curl -H Host:whoami.docker.local http://127.0.0.1
便可以访问 whoami 服务。也可以修改 Host whoami.docker.local 127.0.0.1
,访问 whoami.docker.local
也可以访问 whoami 服务。
3. traefik.toml
traefik
会读取 /etc/traefik/traefik.toml
配置文件进行配置。更多的配置信息可以参考文档,文档中只有 demo,具体的配置项不知道意义可以参考 CLI
也可以使用 traefik --configFile=foo/bar/myconfigfile.yml 指定配置
在 docker 中使用 traefik,可以添加到容器中或使用 volumes 挂载 - ./traefik.toml:/etc/traefik/traefik.toml
traefik 配置文件采用了 toml 格式,可访问官方文档查看其语法 toml。
3.1 Dashboard
traefik.toml
配置文件可通过 api.dashboard
选项配置 Web Ui 控制台。
# Enable API and dashboard
[api]
# Enable the API in insecure mode
#
# Optional
# Default: true
#
insecure = true
# Enabled Dashboard
#
# Optional
# Default: true
#
dashboard = true
可通过 http://localhost:8080
,在本地将 traefik 的 Web Ui 控制台直接打开
如果是在远程服务器上,可通过 ssh 隧道映射到本地进行打开。ssh 隧道命令。
# 左侧为本地 IP:PORT,右侧为远程服务器 IP:PORT
# -N: 用以端口转发
# -L: 将服务器中 localhost:5000 映射到本地 5000 端口
$ ssh -NL [bind_address:]port:host:hostport
$ ssh -NL 8080:localhost:8080 服务器ip
3.2 日志与问题定位
日志极为重要,当某个路由配置不成功,或者 https 配置失败时,可以通过日志文件来定位问题。
通过 log 选项可以配置日志路径与格式。
[log]
filePath = "log/traefik.log"
format = "json"
使用以下语句查看日志
# 取日志前十行,查看其问题
$ cat log/traefik.log | head -10 | jq
3.3 完整版配置文件
traefik.toml
[global]
checkNewVersion = true
sendAnonymousUsage = true
################################################################
# Entrypoints configuration
################################################################
# Entrypoints definition
#
# Optional
# Default:
[entryPoints]
[entryPoints.web]
address = ":80"
[entryPoints.websecure]
address = ":443"
################################################################
# Traefik logs configuration
################################################################
# Traefik logs
# Enabled by default and log to stdout
#
# Optional
#
[log]
filePath = "log/traefik.log"
format = "json"
################################################################
# Access logs configuration
################################################################
# Enable access logs
# By default it will write to stdout and produce logs in the textual
# Common Log Format (CLF), extended with additional fields.
#
# Optional
#
[accessLog]
# Sets the file path for the access log. If not specified, stdout will be used.
# Intermediate directories are created if necessary.
#
# Optional
# Default: os.Stdout
#
filePath = "log/traefik-access.json"
# Format is either "json" or "common".
#
# Optional
# Default: "common"
#
format = "json"
[accessLog.fields]
defaultMode = "keep"
[accessLog.fields.headers]
defaultMode = "keep"
################################################################
# API and dashboard configuration
################################################################
# Enable API and dashboard
[api]
# Enable the API in insecure mode
#
# Optional
# Default: true
#
insecure = true
# Enabled Dashboard
#
# Optional
# Default: true
#
dashboard = true
################################################################
# Ping configuration
################################################################
# Enable ping
[ping]
# Name of the related entry point
#
# Optional
# Default: "traefik"
#
# entryPoint = "traefik"
################################################################
# Docker configuration backend
################################################################
# Enable Docker configuration backend
[providers.docker]
# Docker server endpoint. Can be a tcp or a unix socket endpoint.
#
# Required
# Default: "unix:///var/run/docker.sock"
#
# endpoint = "tcp://10.10.10.10:2375"
# Default host rule.
#
# Optional
# Default: "Host(`{{ normalize .Name }}`)"
#
# Expose containers by default in traefik
#
# Optional
# Default: true
#
# exposedByDefault = false
[metrics.prometheus]
buckets = [0.1,0.3,1.2,5.0]
entryPoint = "metrics"
[certificatesResolvers.le.acme]
email = "xianger94@qq.com"
storage = "acme.json"
[certificatesResolvers.le.acme.tlsChallenge]
[certificatesResolvers.le.acme.httpChallenge]
entryPoint = "web"
3.4 挂载在 traefik 容器中
将 traefik.toml
配置挂载在 traefik 容器中
version: '3'
services:
reverse-proxy:
image: traefik:v2.5
ports:
- "80:80"
- "443:443"
- "8080:8080"
volumes:
- ./traefik.toml:/etc/traefik/traefik.toml # traefik 配置
- ./acme.json:/acme.json # 维护证书信息--证书解析配置
- ./log:/log # 日志文件夹挂载,这样可以在宿主机中直接查看日志
- /var/run/docker.sock:/var/run/docker.sock # 使得 traefik 可以监听 docker 事件
container_name: traefik
env_file: .env # 环境变量以文件形式进行存储配置 https://docs.docker.com/compose/env-file/
labels:
- "traefik.http.routers.api.rule=Host(`traefik.docker.local`)" # 也可以自身设置label 用于 traefik 发现并监控
- "traefik.http.routers.api.service=api@internal" # 指定 api@internal 服务,开启 api 控制。
最后以下指令启动容器
# 新建 acme.json,用以挂载至 traefik 容器中维护证书信息
$ touch acme.json
# 给 acme.json 赋 600 权限非常重要
# 给 acme.json 赋 600 权限非常重要
# 给 acme.json 赋 600 权限非常重要
$ chmod 600 acme.json
$ touch .env
$ docker compose up